home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 7 / Night Owl Shareware (NOPV7)(Night Owl Publisher Inc.)(1992).bin / 038a / bash1_12.arj / BASH1-12.TAR / bash-1.12 / lib / glob / fnmatch.c < prev    next >
C/C++ Source or Header  |  1991-11-23  |  4KB  |  171 lines

  1. /* Copyright (C) 1991 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <errno.h>
  20. #include "fnmatch.h"
  21.  
  22. #if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
  23. extern int errno;
  24. #endif
  25.  
  26. /* Match STRING against the filename pattern PATTERN, returning zero if
  27.    it matches, nonzero if not.  */
  28. int
  29. fnmatch (pattern, string, flags)
  30.      char *pattern;
  31.      char *string;
  32.      int flags;
  33. {
  34.   register char *p = pattern, *n = string;
  35.   register char c;
  36.  
  37.   if ((flags & ~__FNM_FLAGS) != 0)
  38.     {
  39.       errno = EINVAL;
  40.       return -1;
  41.     }
  42.  
  43.   while ((c = *p++) != '\0')
  44.     {
  45.       switch (c)
  46.     {
  47.     case '?':
  48.       if (*n == '\0')
  49.         return FNM_NOMATCH;
  50.       else if ((flags & FNM_PATHNAME) && *n == '/')
  51.         return FNM_NOMATCH;
  52.       else if ((flags & FNM_PERIOD) && *n == '.' &&
  53.            (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  54.         return FNM_NOMATCH;
  55.       break;
  56.  
  57.     case '\\':
  58.       if (!(flags & FNM_NOESCAPE))
  59.         c = *p++;
  60.       if (*n != c)
  61.         return FNM_NOMATCH;
  62.       break;
  63.  
  64.     case '*':
  65.       if ((flags & FNM_PERIOD) && *n == '.' &&
  66.           (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  67.         return FNM_NOMATCH;
  68.  
  69.       for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
  70.         if (((flags & FNM_PATHNAME) && *n == '/') ||
  71.         (c == '?' && *n == '\0'))
  72.           return FNM_NOMATCH;
  73.  
  74.       if (c == '\0')
  75.         return 0;
  76.  
  77.       {
  78.         char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
  79.         for (--p; *n != '\0'; ++n)
  80.           if ((c == '[' || *n == c1) &&
  81.           fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
  82.         return 0;
  83.         return FNM_NOMATCH;
  84.       }
  85.  
  86.     case '[':
  87.       {
  88.         /* Nonzero if the sense of the character class is inverted.  */
  89.         register int not;
  90.  
  91.         if (*n == '\0')
  92.           return FNM_NOMATCH;
  93.  
  94.         if ((flags & FNM_PERIOD) && *n == '.' &&
  95.         (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  96.           return FNM_NOMATCH;
  97.  
  98.         not = (*p == '!' || *p == '^');
  99.         if (not)
  100.           ++p;
  101.  
  102.         c = *p++;
  103.         for (;;)
  104.           {
  105.         register char cstart = c, cend = c;
  106.  
  107.         if (!(flags & FNM_NOESCAPE) && c == '\\')
  108.           cstart = cend = *p++;
  109.  
  110.         if (c == '\0')
  111.           /* [ (unterminated) loses.  */
  112.           return FNM_NOMATCH;
  113.  
  114.         c = *p++;
  115.  
  116.         if ((flags & FNM_PATHNAME) && c == '/')
  117.           /* [/] can never match.  */
  118.           return FNM_NOMATCH;
  119.  
  120.         if (c == '-' && *p != ']')
  121.           {
  122.             cend = *p++;
  123.             if (!(flags & FNM_NOESCAPE) && cend == '\\')
  124.               cend = *p++;
  125.             if (cend == '\0')
  126.               return FNM_NOMATCH;
  127.             c = *p++;
  128.           }
  129.  
  130.         if (*n >= cstart && *n <= cend)
  131.           goto matched;
  132.  
  133.         if (c == ']')
  134.           break;
  135.           }
  136.         if (!not)
  137.           return FNM_NOMATCH;
  138.         break;
  139.  
  140.       matched:;
  141.         /* Skip the rest of the [...] that already matched.  */
  142.         while (c != ']')
  143.           {
  144.         if (c == '\0')
  145.           /* [... (unterminated) loses.  */
  146.           return FNM_NOMATCH;
  147.  
  148.         c = *p++;
  149.         if (!(flags & FNM_NOESCAPE) && c == '\\')
  150.           /* 1003.2d11 is unclear if this is right.  %%% */
  151.           ++p;
  152.           }
  153.         if (not)
  154.           return FNM_NOMATCH;
  155.       }
  156.       break;
  157.  
  158.     default:
  159.       if (c != *n)
  160.         return FNM_NOMATCH;
  161.     }
  162.  
  163.       ++n;
  164.     }
  165.  
  166.   if (*n == '\0')
  167.     return 0;
  168.  
  169.   return FNM_NOMATCH;
  170. }
  171.